/*
 * Copyright (c) 2011, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ALKES_IAPPLICATION_H_INCLUDED_
#define ALKES_IAPPLICATION_H_INCLUDED_

#include "alkes/internal.h"
#include "alkes/sys/IAppDriver.h"

namespace alkes {

enum DeviceType
{
    AL_DEVICE_TYPE_NONE = 0,
    AL_DEVICE_TYPE_OPENGL,
    AL_DEVICE_TYPE_OPENGL_SHADER,
    AL_DEVICE_TYPE_OPENGL_NOSHADER,
    AL_DEVICE_TYPE_OPENGL_ES1,
    AL_DEVICE_TYPE_OPENGL_ES2,
    AL_DEVICE_TYPE_DIRECTX9,
};

typedef IGraphicsDevice* (*GraphicsDeviceFactory)(int device_type, void* native_window);

class AL_EXPORT IApplication
{
public:
    IApplication(const char* title, uint16_t width, uint16_t height);
    virtual ~IApplication();

    void setTitle(const char* title);
    void setSize(uint16_t width, uint16_t height);
    void setDeviceType(DeviceType type);
    void setDebugMode(bool debug_mode);

    const char* getTitle() const;
    uint16_t getWidth() const;
    uint16_t getHeight() const;
    DeviceType getDeviceType() const;
    bool isDebugMode() const;
    virtual NativeWindow getNativeWindow() const = 0;

    IAppDriver* addDriver(IAppDriver* driver);

    GraphicsDeviceFactory setDeviceFactory(GraphicsDeviceFactory factory);
    GraphicsDeviceFactory getDeviceFactory() const;

    int run(int argc, char* argv[]);

    bool invokeInit(IGraphicsDevice* device);
    void invokeFin();
    void invokeDraw();
    void invokeResize(uint16_t new_width, uint16_t new_height);
    void invokeDirty(const Rect& rect);
    void invokePress(KeyEvent key);
    void invokeRelease(KeyEvent key);
    void invokeDeviceEvent(uint16_t device_no, uint64_t value);
    void invokeMouseMove(uint16_t x, uint16_t y);

protected:
    virtual bool initialize(int argc, char* argv[]);
    virtual void finalize();
    virtual void onMainloop();

private:
    IAppDriver*  driver_;
    const char* title_;
    uint16_t width_;
    uint16_t height_;
    DeviceType device_type_;
    GraphicsDeviceFactory factory_;
    bool debug_;
};

}

#endif
